---
title: 레이아웃
description: 일반적인 레이아웃을 위해 페이지 간에 공유되는 Astro 컴포넌트 타입인 레이아웃에 대한 소개입니다.
i18nReady: true
---

import ReadMore from '~/components/ReadMore.astro'

**레이아웃**은 페이지 템플릿과 같은 재사용 가능한 UI 구조를 제공하는 데 사용되는 [Astro 컴포넌트](/ko/basics/astro-components/)입니다.

우리는 일반적으로 머리글, 탐색 모음, 바닥글과 같이 페이지 전체에서 공유되는 공통 UI 요소를 제공하는 Astro 컴포넌트에 대해 "레이아웃"이라는 용어를 사용합니다. 일반적인 Astro 레이아웃 컴포넌트는 다음과 같은 [Astro, Markdown, MDX 페이지](/ko/basics/astro-pages/)를 제공합니다.
- **페이지 셸**(`<html>`, `<head>`, `<body>` 태그)
- 개별 페이지 콘텐츠를 삽입해야 하는 위치를 지정하는 [**`<slot />`**](/ko/basics/astro-components/#슬롯).

하지만 레이아웃 컴포넌트에는 특별한 것이 없습니다! 다른 Astro 컴포넌트처럼 [props를 전달](/ko/basics/astro-components/#컴포넌트-props)받고 [다른 컴포넌트를 가져와 사용](/ko/basics/astro-components/#컴포넌트-구조)할 수 있습니다. 여기에는 [UI 프레임워크 컴포넌트](/ko/guides/framework-components/)와 [클라이언트 측 스크립트](/ko/guides/client-side-scripts/)가 포함될 수 있습니다. 전체 페이지 셸을 제공할 필요도 없으며 대신 부분 UI 템플릿으로 사용할 수 있습니다.

레이아웃 컴포넌트는 일반적으로 프로젝트의 `src/layouts` 디렉터리에 배치되지만 이는 필수 사항은 아닙니다. 프로젝트의 어느 곳에나 배치하도록 선택할 수 있습니다. 심지어 [레이아웃 이름 앞에 `_`를 붙이면](/ko/guides/routing/#페이지-제외) 레이아웃 컴포넌트와 페이지를 같은 위치에 배치할 수도 있습니다.

## 레이아웃 예시

```astro "<slot />" 
---
// src/layouts/MySiteLayout.astro
import BaseHead from '../components/BaseHead.astro';
import Footer from '../components/Footer.astro';
const { title } = Astro.props;
---
<html lang="ko">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <BaseHead title={title}/>
  </head>
  <body>
    <nav>
      <a href="#">홈</a>
      <a href="#">블로그</a>
      <a href="#">연락처</a>
    </nav>
    <h1>{title}</h1>
    <article>
      <slot /> <!-- 콘텐츠가 여기에 삽입됩니다. -->
    </article>
    <Footer />
  </body>
</html>
```

```astro title="src/pages/index.astro"
---
import MySiteLayout from '../layouts/MySiteLayout.astro';
---
<MySiteLayout title="Home Page">
  <p>레이아웃으로 감싼 페이지입니다!</p>
</MySiteLayout>
```

<ReadMore>[슬롯](/ko/basics/astro-components/#슬롯)에 대해 자세히 알아보세요.</ReadMore>

## Markdown/MDX 레이아웃

페이지 레이아웃은 페이지 형식이 없는 [Markdown 및 MDX 페이지](/ko/guides/markdown-content/#markdown-및-mdx-페이지)에 특히 유용합니다.

Astro는 페이지 레이아웃으로 사용할 `.astro` 컴포넌트를 지정하기 위해 특별한 `layout` 프런트매터 속성을 제공합니다.

```markdown title="src/pages/page.md" {2} 
---
layout: ../layouts/BaseLayout.astro
title: "안녕하세요!"
author: "Matthew Phillips"
date: "09 Aug 2022"
---
모든 프런트매터 속성은 Astro 레이아웃 컴포넌트에 대한 props로 사용할 수 있습니다.

`layout` 속성은 Astro에서 제공하는 유일한 특수 속성입니다.

`src/pages/` 디렉터리에 있는 Markdown 및 MDX 파일 모두에서 사용할 수 있습니다.

```

Markdown 또는 MDX 페이지의 일반적인 레이아웃은 다음과 같습니다.

1. Markdown 또는 MDX 페이지의 프런트매터 및 기타 데이터를 사용하기 위한 `frontmatter` prop.
2. 페이지의 Markdown/MDX 콘텐츠가 렌더링되어야 하는 위치를 나타내는 기본 [`<slot />`](/ko/basics/astro-components/#슬롯).

```astro /(?<!//.*){?frontmatter(?:\\.\w+)?}?/ "<slot />"
---
// src/layouts/BaseLayout.astro
// 1. 프런트매터 prop을 통해 프런트매터 및 기타 데이터를 사용할 수 있습니다.
const { frontmatter } = Astro.props;
---
<html>
  <head>
    <!-- 여기에 스타일, 메타 태그 등 다른 Head 요소를 추가하세요. -->
    <title>{frontmatter.title}</title>
  </head>
  <body>
    <!-- 일반적인 머리글 및 바닥글과 같은 다른 UI 컴포넌트를 여기에 추가합니다. -->
    <h1>{frontmatter.title} by {frontmatter.author}</h1>
    <!-- 2. 렌더링된 HTML은 기본 슬롯으로 전달됩니다. -->
    <slot />
    <p>작성: {frontmatter.date}</p>
  </body>
</html>
```


`MarkdownLayoutProps` 또는 `MDXLayoutProps` 도우미를 사용하여 레이아웃의 [`Props` 타입](/ko/guides/typescript/#컴포넌트-props)을 설정할 수 있습니다.


```astro title="src/layouts/BaseLayout.astro" ins={2,4-9}
---
import type { MarkdownLayoutProps } from 'astro';

type Props = MarkdownLayoutProps<{
  // 여기서 프런트매터 props를 정의하세요.
  title: string;
  author: string;
  date: string;
}>;

// 이제 'frontmatter', 'url' 및 기타 Markdown 레이아웃 속성에 타입 안전성을 적용하여 사용할 수 있습니다.
const { frontmatter, url } = Astro.props;
---
<html>
  <head>
    <link rel="canonical" href={new URL(url, Astro.site).pathname}>
    <title>{frontmatter.title}</title>
  </head>
  <body>
    <h1>{frontmatter.title} - {frontmatter.author}</h1>
    <slot />
    <p>작성: {frontmatter.date}</p>
  </body>
</html>
```

### Markdown 레이아웃 Props

Markdown/MDX 레이아웃은 `Astro.props`를 통해 다음 정보를 사용할 수 있습니다.

- **`file`** - 이 파일의 절대 경로(예: `/home/user/projects/.../file.md`).
- **`url`** - 페이지인 경우 해당 페이지의 URL(예: `/en/guides/markdown-content`).
- **`frontmatter`** - Markdown 또는 MDX 문서의 모든 프런트매터.
  - **`frontmatter.file`** - 최상위 `file` 속성과 동일합니다.
  - **`frontmatter.url`** - 최상위 `url` 속성과 동일합니다.
- **`headings`** - 관련 메타데이터가 있는 Markdown 또는 MDX 문서의 제목(`h1 -> h6`)들의 목록입니다. 이 목록은 다음 타입을 따릅니다: `{ depth: number; slug: string; text: string }[]`
- **(Markdown만 해당) `rawContent()`** - 원시 Markdown 문서를 문자열로 반환하는 함수입니다.
- **(Markdown만 해당) `compiledContent()`** - HTML 문자열로 컴파일된 Markdown 문서를 반환하는 함수입니다.

Markdown 블로그 게시물의 예는 다음과 같은 `Astro.props` 객체를 레이아웃에 전달할 수 있습니다.

```js
Astro.props = {
  file: "/home/user/projects/.../file.md",
  url: "/en/guides/markdown-content/",
  frontmatter: {
    /** 블로그 게시물의 프런트매터 */
    title: "Astro 0.18 릴리스",
    date: "Tuesday, July 27 2021",
    author: "Matthew Phillips",
    description: "Astro 0.18은 Astro 출시 이후 가장 큰 릴리스입니다.",
    /** 생성된 값 */
    file: "/home/user/projects/.../file.md",
    url: "/en/guides/markdown-content/"
  },
  headings: [
    {
      "depth": 1,
      "text": "Astro 0.18 릴리스",
      "slug": "astro-018-릴리스"
    },
    {
      "depth": 2,
      "text": "반응성 부분 수화",
      "slug": "반응성-부분-수화"
    }
    /* ... */
  ],

  /** Markdown에서만 사용 가능 */
  rawContent: () => "# Astro 0.18 릴리스\n한 달 남짓 전에 첫 번째 공개 베타가 시작되었습니다. [...]",
  compiledContent: () => "<h1>Astro 0.18 릴리스</h1>\n<p>한 달 남짓 전에 첫 번째 공개 베타가 시작되었습니다. [...]</p>",
}
```

:::note
Markdown/MDX 레이아웃은 `Astro.props`를 통해 모든 파일에서 [내보낸 속성들](/ko/guides/markdown-content/#내보낸-속성)을 사용할 수 있지만 **몇 가지 차이점이 있습니다**.

* 제목 정보(예: `h1 -> h6` 요소)는 `getHeadings()` 함수가 아닌 `headings` 배열을 통해 사용할 수 있습니다.

* *또한* `file` 및 `url`은  중첩된 `frontmatter` 속성(예: `frontmatter.url` 및 `frontmatter.file`)으로 사용할 수도 있습니다.

* 프런트매터 외부에 정의된 값(예: MDX의 `export` 문)은 사용할 수 없습니다. 대신 [레이아웃 가져오기](#수동으로-레이아웃-가져오기-mdx)를 고려해 보세요.
:::

### 수동으로 레이아웃 가져오기 (MDX)

프런트매터에 존재하지 않거나 존재할 수 없는 정보를 MDX 레이아웃에 전달해야 할 수도 있습니다. 이 경우 대신 [`<Layout />` 컴포넌트](/ko/basics/layouts/)를 가져와 사용하고 다른 컴포넌트처럼 props를 전달할 수 있습니다.

```mdx title="src/pages/posts/first-post.mdx" ins={6} del={2} /</?BaseLayout>/ /</?BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>/
---
layout: ../../layouts/BaseLayout.astro
title: '나의 첫 MDX 게시물'
publishDate: '21 September 2022'
---
import BaseLayout from '../../layouts/BaseLayout.astro';

export function fancyJsHelper() {
  return "YAML로 시도해 보세요!";
}

<BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}>
  MDX를 사용하는 새 Astro 블로그에 오신 것을 환영합니다!
</BaseLayout>
```

그러면 레이아웃의 `Astro.props`를 통해 값을 사용할 수 있으며 MDX 콘텐츠는 `<slot />` 컴포넌트가 작성된 페이지에 삽입됩니다.

```astro /{?title}?/ "fancyJsHelper" "{fancyJsHelper()}"
---
// src/layouts/BaseLayout.astro
const { title, fancyJsHelper } = Astro.props;
---
<!-- -->
<h1>{title}</h1>
<slot /> <!-- 콘텐츠가 여기에 삽입됩니다 -->
<p>{fancyJsHelper()}</p>
<!-- -->
```

<ReadMore>[Markdown/MDX 안내서](/ko/guides/markdown-content/)에서 Astro의 Markdown 및 MDX 지원에 대해 자세히 알아보세요.</ReadMore>

## `.md`, `.mdx`, `.astro`에 하나의 레이아웃 사용

단일 Astro 레이아웃을 작성하여 `.md` 및 `.mdx` 파일의 `frontmatter` 객체는 물론, `.astro` 파일에서 전달된 모든 명명된 props를 수신할 수 있습니다.

아래 예에서 레이아웃은 프런트매터 YAML `title` 속성 또는 `title` 속성을 전달하는 Astro 컴포넌트에서 페이지 제목을 표시합니다.

```astro /{?title}?/ /Astro.props[.a-z]*/
---
// src/components/MyLayout.astro
const { title } = Astro.props.frontmatter || Astro.props;
---
<html>
  <head></head>
  <body>
    <h1>{title}</h1>
    <slot />
  </body>
</html>
```

## 중첩 레이아웃

레이아웃 컴포넌트는 HTML의 전체 페이지를 포함할 필요가 없습니다. 레이아웃을 더 작은 컴포넌트로 나누고 레이아웃 컴포넌트를 결합하여 더욱 유연한 페이지 템플릿을 만들 수 있습니다. 이 패턴은 여러 레이아웃에서 일부 코드를 공유하려는 경우에 유용합니다.

예를 들어, `BlogPostLayout.astro` 레이아웃 컴포넌트는 게시물의 제목, 날짜, 작성자의 스타일을 지정할 수 있습니다. 그리고 사이트 전체 `BaseLayout.astro`가 탐색, 바닥글, SEO 메타 태그, 전역 스타일, 글꼴과 같은 페이지 템플릿의 나머지 부분을 처리할 수 있습니다. 또한, 다른 중첩 컴포넌트와 마찬가지로 게시물에서 받은 props를 다른 레이아웃으로 전달할 수도 있습니다.

```astro {3} /</?BaseLayout>/ /</?BaseLayout url={frontmatter.url}>/
---
// src/layouts/BlogPostLayout.astro
import BaseLayout from './BaseLayout.astro';
const { frontmatter } = Astro.props;
---
<BaseLayout url={frontmatter.url}>
  <h1>{frontmatter.title}</h1>
  <h2>게시물 작성자: {frontmatter.author}</h2>
  <slot />
</BaseLayout>
```
